<?php
/**
 * 购物车控制器
 */
namespace app\index\controller;
use app\index\controller\Common;
class Cart extends Common{
	/**
     * 购物车列表页
     */
    public function lst(){

    	// 设置页面信息
        $this->setPageMsg( '购物车列表页', '购物车列表页关键字', '购物车列表页描述', ['cart','common','bottomnav'], ['cart1'] );

        // 获取购物车信息
        if( session('mid') ){ // 检测用户是否登录

        	// 从数据库获取购物车信息
        	$info = db('cart')->where( 'mid','=',session('mid') )->select();

        	// 循环拼凑与cookie内商品结构一致的数据
        	$data = [];
        	foreach ($info as $v) {

        		$data[$v['gid'].'-'.$v['attr_list']] = $v['num'];

        	}

        }else{

        	// 从cookie中获取购物车信息
        	$data = cookie('cart') ? unserialize( cookie('cart') ) : [];

        }
        
        if( $data ){

	     	// 拼凑展示购物车信息结构
	        $carts = $this->goodsInfo($data);

        }else{

            // 没有商品就跳转回原页面
            if( session('returnUrl') ){

                $url = session('returnUrl');
                session('returnUrl',null);

            }else {

                $url = url('index/index');

            }

        	$this->error('先逛逛吧，购物车内还没添加商品！',$url);
        }
    
        //分配变量
        $this->assign('carts',$carts['carts']);
        $this->assign('totalPrice',number_format($carts['totalPrice'],2,'.',''));
        
    	//展示视图
    	return $this->fetch();
    }

    /**
     * 添加购物车
     */
    public function add(){

    	// 安全处理 
		if( !request()->isPost() ){

			$this->error('您访问的页面不存在！');

		}
		
    	// 收集信息
    	$gid = input('post.goods_id') + 0;
    	$num = input('post.amount') + 0;
    	$attr_list = input('post.goods_attr_id/a') ? input('post.goods_attr_id/a') : ['0'];
        
        // 检测用户提交的信息
        if( input('post.hasAttrs')+0 ){

            // 检测用户是否选择了属性
            if( !array_filter($attr_list) ){

                $this->error('请选择属性后再来添加购物车！');

            }else{

                // 检测货品是否存在，和库存是否充足
                $list = implode(',', $attr_list);
                $sku = db('product')->where(['attr_list'=>$list,'gid'=>$gid])->value('product_sku');
                
                if( $sku === 0 ){

                    // 库存不足
                    $this->error('库存不足，目前该商品仅有：'.$sku.'件');

                }else if( !$sku ){

                    // 属性组合不存在
                    $this->error('你选择的属性组合不存在，请检查是否选择有误！');

                }

            }


        }
      
    	//是否登录
    	if( session('mid') ){

    		// 将数组变成字符串
    		$attr_list = implode(',', $attr_list);

    		// 向数据库中添加购物车数据
    		$this->insertCart($gid, $attr_list, $num);

    		
    	}else{       

    		// 检测cookie中是否已经存在购物车商品，存在就取出，不存在就给一个空数组
    		$cart = cookie('cart') ? unserialize( cookie('cart') ) : [];

    		// 购物车键名，由商品id与属性id列表组成
    		$key = $gid.'-'.implode(',', $attr_list);

    		// 检测购物车内是否已经添加过该商品
			if( isset( $cart[$key] ) ){

				// 添加过就将数量相加
				$cart[$key]+=$num;

			}else{

				// 没添加过就赋值
				$cart[$key] = $num;

			}

			// 序列化购物车信息
    		$cookie = serialize($cart);

    		// 设置cookie，储存购物车
    		cookie('cart',$cookie,time()+config('cart_cookie_lifetime'),'/','jds.com');   
               	
    	}

    	//跳转到购物车列表
    	$this->success('添加购物车成功，即将跳转到购物车列表进行结算！',url('lst'));

    }

    /**
     * 异步修改购物车
     */
    public function edit(){

    	// 安全处理 
		if( !request()->isAjax() ){

			$this->error('您访问的页面不存在！');

		}
		
    	// 收集信息
    	$gid = input('id') + 0;
    	$num = input('amount') + 0;
    	$attr_list = input('attrList');

    	// 检测库存
        if( $attr_list ) {

            // 如果存在属性列表，就在货品表中查库存
    	    $sku = db('product')->where(['gid'=>$gid,'attr_list'=>$attr_list])->value('product_sku');

        }else {

            // 如果不存在属性列表，就在商品表中查库存
            $sku = db('goods')->where(['gid'=>$gid])->value('goods_sku');
        }
    	
    	if( $sku < $num){

    		echo json_encode(['status'=>false,'msg'=>'库存不足，目前该商品仅有：'.$sku.'件']);
    		die;

    	}

    	//是否登录
    	if( session('mid') ){
    		
    		// 更新商品数量
    		db('cart')->strict(true)->where(['gid'=>$gid,'attr_list'=>$attr_list,'mid'=>session('mid')])->update(['num'=>$num]);

    	}else{

    		// 检测cookie中是否已经存在购物车商品，存在就取出，不存在就给一个空数组
    		$cart = cookie('cart') ? unserialize( cookie('cart') ) : [];

    		// 购物车键名，由商品id与属性id列表组成
    		$key = $gid.'-'.$attr_list;

    		// 设置该商品数量
			$cart[$key] = $num;

			// 序列化购物车信息
    		$cookie = serialize($cart);

    		// 设置cookie，储存购物车
    		cookie('cart',$cookie,time()+config('cart_cookie_lifetime'),'/','jds.com');
	    	
    	}

    	// 返回数据
    	echo json_encode(['status'=>true,'msg'=>'修改成功！']);

    }

    /**
     * 异步删除购物车
     */
    public function del(){

    	// 安全处理 
		if( !request()->isAjax() ){

			$this->error('您访问的页面不存在！');

		}
		
    	// 收集信息
    	$gid = input('id') + 0;
    	$attr_list = input('attrList');

    	//是否登录
    	if( session('mid') ){

    		// 删除购物车信息
    		db('cart')->where(['gid'=>$gid,'attr_list'=>$attr_list,'mid'=>session('mid')])->delete();
    		
    	}else{

    		// 检测cookie中是否已经存在购物车商品，存在就取出，不存在就给一个空数组
    		$cart = cookie('cart') ? unserialize( cookie('cart') ) : [];

    		// 购物车键名，由商品id与属性id列表组成
    		$key = $gid.'-'.$attr_list;

    		// 删除购物车商品
    		unset($cart[$key]);

    		if( !empty($cart) ){

				// 序列化购物车信息
	    		$cookie = serialize($cart);

	    		// 设置cookie，储存购物车
	    		cookie('cart',$cookie,time()+config('cart_cookie_lifetime'),'/','jds.com');

    		}else{

    			cookie('cart',null);

    		}

    	}

    	// 返回数据
    	echo json_encode(['status'=>true,'msg'=>'修改成功！']);

    }

    /**
     * 将cookie购物车的信息加入数据库中
     */
    public function cookieToDatabase(){

    	if(cookie('cart')){

    		// 获取购物车信息
    		$carts = unserialize( cookie('cart') );

    		// 循环将购物车信息插入数据库
    		foreach ($carts as $k => $v) {

    			// 拆分商品id与属性id列表
    			$list = explode('-', $k);

    			// 向数据库中添加购物车数据
    			$this->insertCart($list[0],$list[1],$v);

    		}

    		// 清除cookie中的购物车信息
    		cookie('cart',null);

    	}

    }

    /**
     * 向数据库中添加购物车数据
     */
    private function insertCart( $gid,$list,$num ){

    	// 实例化购物车模型
    	$cartModel = db('cart');
        $cid = $cartModel->where([ 'gid'=>$gid,'attr_list'=>'0' ])->value('cid');
     //    echo $cartModel->getLastSql();
    	 // q( cookie('cart') );
    	// 检测数据库中是否已经存在该商品
		if( $cid = $cartModel->where([ 'gid'=>$gid,'attr_list'=>$list ])->value('cid') ){
			
			// 增加数量
			$cartModel->where('cid','=',$cid)->setInc('num',$num);

		}else{

			// 拼凑信息
			$data['attr_list'] = $list;
			$data['num'] = $num;
			$data['mid'] = session('mid');
			$data['gid'] = $gid;
            
			// 插入数据库
			$cartModel->strict(true)->insert($data);

		}

    }

    /**
     * 订单也展示
     */
    public function order(){
        
        // 获取数据
        $buyThis = input('post.buythis/a');
        
        // 检测是否选择了商品
        if( !$buyThis ){

            // 如果是登录后跳转过来的，要检测session中是否存在选中商品
            $buyThis = session('buythis');
            session('buythis',null);

            // 如果没有就跳转回购物车页面
            if ( !$buyThis ) {
                
                $this->error('请选择要购买的商品！',url('lst'));
            }


        }

        // 检测用户是否登录
        if( !session('mid') ){

            session('buythis',$buyThis);

            session('returnUrl',url('order'));

            $this->error('请先登录后，进行结算',url('member/loginShow'));

        }

        // 设置页面信息
        $this->setPageMsg( '订单页', '订单页关键字', '订单页描述', ['fillin','bottomnav'], ['cart2'] );

        // 获取收货人地址信息
        $address = db('address')->where( 'mid','=',session('mid') )->select();
        
        // 检测是否设置了默认收货人地址
        $defalutAddr = [];
        $cityModel = db('city');
        foreach ($address as $k=>$v) {

            // 获取省市区id
            $cids = [ $v['province'],$v['city'],$v['district'] ];

            // 根据id获取省市区名称与id
            $city = $cityModel->field('cid,city_name')->where( 'cid','in',$cids )->select(); 

            // 将对应的省市区信息添加到$address地址信息中
            foreach ($city as $v1) {

                // 省
                if( $v['province'] == $v1['cid'] ) {

                    $address[$k]['province'] =$v1;

                }
                // 市
                else if( $v['city'] == $v1['cid'] ) {

                    $address[$k]['city'] =$v1;

                }
                // 区
                else if( $v['district'] == $v1['cid'] ) {

                    $address[$k]['district'] =$v1;

                }
                
            }
            
            // 如果存在默认地址，将默认地址取出
            if( $v['default'] ) {

                $defalutAddr = $address[$k];

            }
            
        }

        // 获取一级城市
        $citys = db('city')->field('cid,city_name')->where(['pid'=>0,'status'=>1])->select();

        // 获取物流方式
        $ships = db('ship')->select();

        // 获取支付方式
        $pays = db('pay')->select();
        
        // 获取选取的商品信息
        $gids = [];
        $lists = [];
        foreach ($buyThis as $v) {
            
            $info = explode('-', $v);
            $gids[] = $info[0];
            $lists[] = $info[1];
        }

        // 从数据库获取购物车信息
        $msg = db('cart')->where( ['gid'=>['in',$gids],'attr_list'=>['in',$lists]] )->select();

        // 循环拼凑与cookie内商品结构一致的数据
        $data = [];
        foreach ($msg as $v) {

            $data[$v['gid'].'-'.$v['attr_list']] = $v['num'];

        }     

        // 拼凑展示购物车信息结构
        $carts = $this->goodsInfo($data);       
        // q($defalutAddr);
        //分配变量
        $this->assign('address',$address);
        $this->assign('defalutAddr',$defalutAddr);
        $this->assign('citys',$citys);
        $this->assign('ships',$ships);
        $this->assign('pays',$pays); 
        $this->assign('carts',$carts['carts']);
        $this->assign('totalPrice',number_format($carts['totalPrice'],2,'.',''));
        
        //展示视图
        return $this->fetch();

    }

    /**
     * 下订单
     */
    public function addOrder(){
        
        // 安全处理 
        if( !request()->isPost() ){

            $this->error('您访问的页面不存在！');

        }

        // 获取信息
        $msg = input('post.');
        // q($msg);
        // 验证信息
        $validate = new \think\Validate([
            'shr_consignee'  => 'require', 
            'shr_mobile' => '^1[34578]{1}[0-9]{9}$',
            'shr_tel' => ['regex'=>'/^(\d{3}-\d{8}|\d{4}-\d{7})$/'],
            'shr_email' => 'email',
            'shr_zipcode' => '^[1-9][0-9]{5}$',
            'shr_address' => 'require',
            'post_method' => 'number',
            'pay_method' => 'number'
        ]);
        
        if ( !$validate->check($msg) ) {
            $this->error( $validate->getError() );
        }

        // 验证是否提交了商品
        $goods = $msg['goods'];

        if( !$goods ) {
            $this->error( '没有选择商品！' );
        }

        // 获取物流信息
        $ship = db('ship')->where( 'sid','=',$msg['post_method']+0 )->find();
        
        // 获取支付信息
        $pay = db('pay')->where( 'pid','=',$msg['pay_method']+0 )->find();

        // 开启文件锁
        $file = fopen('orderLock.txt', 'r');
        $lock = flock($file, LOCK_EX );

        // 生成15位订单号（时间戳+5为唯一随机数）
        $code = time().mt_rand(10000,99999);

        // 拼凑数据
        $data['order_sn'] = $code;
        $data['created'] = time();
        $data['consignee'] = $msg['shr_consignee'];
        $data['mobile'] = $msg['shr_mobile'];
        $data['tel'] = $msg['shr_tel'];
        $data['email'] = $msg['shr_email'];
        $data['province'] = $msg['shr_province'];
        $data['city'] = $msg['shr_city'];
        $data['district'] = $msg['shr_district'];
        $data['address'] = $msg['shr_address'];
        $data['zipcode'] = $msg['shr_zipcode'];
        $data['ship_name'] = $ship['ship_name'];
        $data['ship_price'] = $ship['ship_price'];
        $data['pay_name'] = $pay['pay_name'];
        $data['total_price'] = $msg['totalPrice']+0;
        $data['mid'] = session('mid');
       
        // 添加数据到数据库
        $db = db('order');
        if( $db->strict('true')->insert( $data ) ){

            // 获取最后插入的id
            $id = $db->getLastInsID();

            // 循环插入订单商品
            $flag = true; 
            $errorMsg = [];
            $goodsModel = db('goods');
            $productModel = db('product');
            $ogModel = db('order_goods');
            $memberModel = db('member');
            foreach ( $goods as $k => $v ) {
                
                // 获取商品
                $good = $goodsModel->field('goods_code,is_on_sale,is_delete,goods_sku,pic_small,jifen,jyz')->where( 'gid','=',$v['gid'] )->find();
                
                // 检测商品是否下架
                if( !$good['is_on_sale'] || $good['is_delete'] ) {

                     $flag = false; 
                     $errorMsg['not_sale'][] = $v['goods_name'];

                }
                
                // 检测商品库存量是否充足
                $product = $productModel->field('product_sku,product_code')->where( ['attr_list'=>$k,'gid'=>$v['gid']] )->find();
                if( $product ) {

                    if( $v['num'] > $product['product_sku'] ) {
                        $flag = false; 
                        $errorMsg['not_sku'][] = $v['goods_name'];
                    }

                }else {

                    if( $v['num'] > $good['goods_sku'] ) {
                        $flag = false; 
                        $errorMsg['not_sku'][] = $v['goods_name'];
                    }

                }

                if( $flag ) {

                    // 收集信息
                    $info['goods_name'] = $v['goods_name'];
                    $info['goods_price'] = $v['price'];
                    $info['goods_num'] = $v['num'];
                    $info['goods_sn'] = $product['product_code'] ? $product['product_code']: $good['goods_code'];
                    $info['pic'] = $good['pic_small'];
                    $info['attr_ids'] = $k;
                    $info['attr_value'] = $v['attr_value'];
                    $info['rid'] = $id;
                    $info['mid'] = session('mid');
                    $info['gid'] = $v['gid'];

                    // 插入订单商品
                    if( $ogModel->strict('true')->insert( $info ) ){

                        // 删除购物车对应商品
                        db('cart')->where( [ 'mid'=>session('mid'),'gid'=>$v['gid'],'attr_list'=>$info['attr_ids'] ] )->delete();

                        // 减少库存
                        if( $info['attr_ids'] ){

                            $productModel->where( ['attr_list'=>$k,'gid'=>$v['gid'] ] )->setDec('product_sku',$v['num']);

                        }else{

                            $goodsModel->where( 'gid',$v['gid'] )->setDec('goods_sku',$v['num']);

                        }

                        // 添加积分和经验值
                        $memberModel->where( 'mid','=',session('mid') )->inc('jifen',$good['jifen']*$v['num'])->inc('jyz',$good['jyz']*$v['num'])->update();
                        
                    }else{
                        $flag = false; 
                        $errorMsg['not_goods'][] = $v['goods_name'];
                    }
                    

                }
                
            }

            // 释放文件锁
            flock($file, LOCK_UN );

            // 如果添加订单时候有错误
            if( !$flag ) {

                // 拼凑错误信息
                $msg = '';
                
                // 拼凑商品已下架信息
                if( isset($errorMsg['not_sale']) ) {

                    $g = implode(';', $errorMsg['not_sale']);
                    $msg.='以下商品已下架：'.$g.';商品1;商品2;商品1;商品1;商品1;商品1<br />';
                    
                }

                // 拼凑商品库存不足信息
                if( isset($errorMsg['not_sku']) ) {

                    $g = implode(';', $errorMsg['not_sku']);
                    $msg.='以下商品库存不足：'.$g.';商品1;商品2;商品1;商品1;商品1;商品1<br />';
                    
                }
                
                // 拼凑商品购买失败信息
                if( isset($errorMsg['not_goods']) ) {

                    $g = implode(';', $errorMsg['not_goods']);
                    $msg.='以下商品购买失败：'.$g.';商品1;商品2;商品1;商品1;商品1;商品1';
                    
                }

                // 输出错误信息
                echo $msg.'<br /><br /> <a href="'.url('lst').'">返回购物车列表</a>';

            }else {

                // 添加成功跳转
                $this->success( '添加成功！',url('orderOk') );

            }


        }else{

            $this->error( '添加失败！' );

        }
    }

    /**
     * 完成订单
     */
    public function orderOk(){

        //设置页面信息
        $this->setPageMsg( '下单成功', '下单成功关键字', '下单成功描述', ['success','bottomnav'], ['profile'] );

        //展示视图
        return $this->fetch('order_ok');
    }


    /**
     * 拼凑购物车或订单商品数据
     */
    private function goodsInfo( $data ){

        // 拼凑展示购物车信息结构
        $carts = [];
        $totalPrice = 0;
        foreach ($data as $k => $v) {
            
            // 根据'-'将商品id和属性列表分开
            $list = explode('-', $k);
            $list[0] = $list[0]+0;

            // 获取商品
            $good = db('goods')->field('shop_price,static_url,is_promote,promote_start_time,promote_end_time,promote_price,is_on_sale,is_delete,goods_name,pic_small')->where('gid','=',$list[0])->find();
            
            if( $good ){

                if( $list[1] ){

                    // 获取货品价格
                    $proPrice = db('product')->where('attr_list','=',$list[1])->value('product_price');

                    // 处理属性与属性值信息
                    $attrs = db('goods_attrs as ga')->field('ga.attr_value,a.attr_name')->join('attrs a','ga.aid = a.aid','LEFT')->where('id','in',$list[1])->select();

                }else{

                    // 获取货品价格
                    $proPrice = $good['shop_price'];

                    // 处理属性与属性值信息
                    $attrs = [ ['attr_name'=>'商品属性','attr_value'=>'默认属性'] ];

                }
              
                // 如果商品处于上架状态，并且没有放入回收站
                if( $good['is_on_sale'] == 1 && $good['is_delete'] == 0 ) {

                    // 处理价格
                    if($good["is_promote"] == 1 && $good["promote_start_time"] < time() && $good["promote_end_time"] > time() ){ 

                       $price = $good["promote_price"];

                    }else if( session('level') ){ 

                        $mprice = db("member_price")->where(["gid" => $list[0],"lid" => session('level')])->value("member_price");

                        if( $mprice >0  ){ // 会员价格大于0就按照会员价格

                           $price = $mprice; 

                        }else if( $mprice == 0  ){ // 会员价格等于0就按照折扣率算

                            $level = config("member.level");
                            $rate = $level[session('level')][2]/100;
                            $price = number_format( round( $proPrice * $rate ), 2, '.',''); 

                        }else{ //否则就按照本店家
                            
                           $price = $proPrice;

                        } 

                    }else{ //否则就按照本店价

                       $price = $proPrice;

                    } 
                    
                    // 拼凑购物车商品信息
                    $carts[$k] = [
                        'gid' => $list[0],
                        'goods_name' => $good['goods_name'],
                        'static_url' => $good['static_url'],
                        'pic' => $good['pic_small'],
                        'attr_list' => $list[1],
                        'attr_value' => $attrs,
                        'price' => $price,
                        'num' => $v,
                        'mid' => 0
                    ];

                    // 计算总金额
                    ;
                    $totalPrice += $price*$v;

                }

            } 

        }
        
        // 返回整理好的数据
        return ['carts'=>$carts,'totalPrice'=>$totalPrice];

    }


}